home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers1.zip / ARCNET.ASM < prev    next >
Assembly Source File  |  1992-01-23  |  14KB  |  600 lines

  1. ;History:11,24
  2. ;Sun Jan 05 22:13:40 1992 increased RST_IVAL to 7.
  3. ;Tue Feb 27 10:56:15 1990 send_pkt wasn't timing out properly.
  4. version    equ    0
  5.  
  6.     include    defs.asm
  7.  
  8. ;Ported from Philip Prindeville's arcnet driver for PCIP
  9. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  10.  
  11. ;  Copyright, 1988-1992, Russell Nelson
  12.  
  13. ;   This program is free software; you can redistribute it and/or modify
  14. ;   it under the terms of the GNU General Public License as published by
  15. ;   the Free Software Foundation, version 1.
  16. ;
  17. ;   This program is distributed in the hope that it will be useful,
  18. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. ;   GNU General Public License for more details.
  21. ;
  22. ;   You should have received a copy of the GNU General Public License
  23. ;   along with this program; if not, write to the Free Software
  24. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  
  26. code    segment    word public
  27.     assume    cs:code, ds:code
  28.  
  29.  
  30. ;Registers:
  31.  
  32. ;the following I/O addresses are mapped to the COM 9026
  33. IMASK        equ    0        ; writeable
  34. STATUS        equ    0        ; readable
  35. COMMAND        equ    1
  36. ;the following I/O addresses are mapped to the 8253 counter/timer
  37. CNTR0        equ    4
  38. CNTR1        equ    5
  39. CNTR2        equ    6
  40. MODE        equ    7
  41. ;reading the following I/O addresse performs a software reset.
  42. SW_RST        equ    8
  43.  
  44. ; time needed to do various things (in clock ticks)
  45. RST_IVAL    equ    7        ;reset
  46. SEND_IVAL    equ    4        ;send
  47.  
  48. ; ARP type for ARCnet
  49. ARP_ARC        equ    007h
  50.  
  51. ; broadcast address is nid 0
  52. ARC_BCAST    equ    0
  53.  
  54. ; packet sizes
  55. ARC_MTU        equ    253
  56. ARC_MnTU    equ    257
  57. ARC_XMTU    equ    508
  58. ;
  59. ;status/interrupt mask bit fields
  60. ;
  61. ST_TA        equ    001h        ; transmitter available
  62. ST_TMA        equ    002h        ; transmitted msg. ackd
  63. ST_RECON    equ    004h        ; system reconfigured
  64. ST_TEST        equ    008h        ; test flag
  65. ST_POR        equ    010h        ; power-on-reset
  66. ST_ETS1        equ    020h        ; unused
  67. ST_ETS2        equ    040h        ; unused
  68. ST_RI        equ    080h        ; receiver inhibited
  69.  
  70. ;
  71. ;in the command register, the following bits have these meanings:
  72. ;        0-2    command
  73. ;        3-4    page number (enable rvc/xmt)
  74. ;         7    rcv b'casts
  75.  
  76.  
  77. DSBL_XMT    equ    001h        ; disable transmitter
  78. DSBL_RCV    equ    002h        ; disable receiver
  79. ENBL_XMT    equ    003h        ; enable transmitter
  80. ENBL_RCV    equ    004h        ; enable receiver
  81. DFN_CONF    equ    005h        ; define configuration
  82. CLR_FLGS    equ    006h        ; clear flags
  83. LD_TST_FLG    equ    007h        ; load test flags
  84.  
  85. ; flags for clear flags operation
  86.  
  87. FL_POR        equ    008h        ; power-on-reset
  88. FL_RECON    equ    010h        ; system reconfigured
  89.  
  90. ; flags for load test flags operation
  91.  
  92. FL_TST        equ    008h        ; test flag (diagnostic)
  93.  
  94. ; byte deposited into first address of buffers when POR
  95. TSTWRD        equ    0321Q
  96.  
  97. ; handy macros for enable receiver/transmitter
  98.  
  99. BCAST        equ    080h        ; receiver only
  100. ;PAGE        equ(nn)    ((nn)<<3)
  101.  
  102. ; flags for define configuration
  103.  
  104. CONF_NORM    equ    000h        ; 1-253 byte packets
  105. CONF_XTND    equ    008h        ; 256-508 byte packets
  106.  
  107. ; macros to access buffers
  108. ;BUF    equ(page)    (((custom.c_basemem) + 512 * (page)))
  109.  
  110. ; ARCnet pseudo header -- note that syscode must occupy last byte...
  111.  
  112. arc_hdr    struc
  113. arc_sid        db    ?        ; source, valid on rcv
  114. arc_did        db    ?        ; destination, 0 = b'cast
  115. arc_cp        db    ?        ; continuation pointer. zero
  116.                     ; for extended packets
  117. arc_xcp        db    ?        ; extended cp, see above
  118. arc_syscode    db    ?        ; system code/pkt type
  119. arc_hdr    ends
  120.  
  121. ; designations for receiver/transmitter buffers.  sorry, no cleverness here
  122. RCVPAGE        equ    2
  123. XMTPAGE        equ    3
  124.  
  125. my_arcnet_id    db    0            ;my arcnet ID.
  126.  
  127.     public    int_no
  128. int_no        db    5,0,0,0        ; interrupt number.
  129. io_addr        dw    02e0h,0        ; I/O address for card (jumpers)
  130. mem_base    dw    0d800h,0
  131.  
  132.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  133. driver_class    db    8,0        ;ARCnet (from the packet spec)
  134. driver_type    db    1        ;Datapoint RIM (from the packet spec)
  135. driver_name    db    'ARCnet',0    ;name of the driver.
  136. driver_function    db    2
  137. parameter_list    label    byte
  138.     db    1    ;major rev of packet driver
  139.     db    9    ;minor rev of packet driver
  140.     db    14    ;length of parameter list
  141.     db    1    ;length of MAC-layer address
  142.     dw    507    ;MTU, including MAC headers
  143.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  144.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  145.     dw    0    ;(# of successive xmits) - 1
  146. int_num    dw    0    ;Interrupt # to hook for post-EOI
  147.             ;processing, 0 == none,
  148.  
  149.     public    rcv_modes
  150. rcv_modes    dw    4        ;number of receive modes in our table.
  151.         dw    0,0,0,rcv_mode_3
  152.  
  153.     include    movemem.asm
  154.  
  155.     public    as_send_pkt
  156. ; The Asynchronous Transmit Packet routine.
  157. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  158. ;   interrupts possibly enabled.
  159. ; Exit with nc if ok, or else cy if error, dh set to error number.
  160. ;   es:di and interrupt enable flag preserved on exit.
  161. as_send_pkt:
  162.     ret
  163.  
  164.     public    drop_pkt
  165. ; Drop a packet from the queue.
  166. ; Enter with es:di -> iocb.
  167. drop_pkt:
  168.     assume    ds:nothing
  169.     ret
  170.  
  171.     public    xmit
  172. ; Process a transmit interrupt with the least possible latency to achieve
  173. ;   back-to-back packet transmissions.
  174. ; May only use ax and dx.
  175. xmit:
  176.     assume    ds:nothing
  177.     ret
  178.  
  179.  
  180.     public    send_pkt
  181. send_pkt:
  182. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  183. ;  (only if the high-performance bit is set in driver_function)
  184. ;enter with ds:si -> packet, cx = packet length.
  185. ;exit with nc if ok, or else cy if error, dh set to error number.
  186.     assume    ds:nothing
  187.  
  188. ;Wait for transmitter ready.
  189.     loadport
  190.     setport    STATUS
  191.  
  192.     mov    ax,SEND_IVAL        ;only wait this long for it.
  193.     call    set_timeout        ;  otherwise we can't send.
  194. send_pkt_3:
  195.     in    al,dx            ;if not busy, exit.
  196.     and    al,ST_TA
  197.     jne    send_pkt_2
  198.     call    do_timeout        ;did we time out yet?
  199.     jne    send_pkt_3        ;no, not yet.
  200.  
  201.     setport    COMMAND            ;stop the transmit.
  202.     mov    al,DSBL_XMT
  203.     out    dx,al
  204.     mov    dh,CANT_SEND        ;timed out, can't send.
  205.     stc
  206.     ret
  207.  
  208. send_pkt_2:
  209. ;store the packet on the board.
  210.     mov    es,mem_base
  211.     mov    di,XMTPAGE * 512
  212.     movsw                ;move the SID and DID to the board.
  213.     sub    cx,2            ;leave them out of the count.
  214.  
  215.     cmp    cx,ARC_XMTU        ;is this one too big?
  216.     ja    send_pkt_toobig        ;yes, can't store it.
  217.     cmp    cx,ARC_MTU        ;is this one small enough
  218.     jbe    send_pkt_1        ;yes, just move it in.
  219.     cmp    cx,ARC_MnTU        ;is it *too* large AND *too* small?
  220.     jae    send_pkt_5        ;no.
  221.     mov    cx,ARC_MnTU        ;yes - use the larger size.
  222. send_pkt_5:
  223.     xor    al,al            ;use a zero cp to indicate xcp.
  224.     mov    ah,cl            ;store the length in xcp.
  225.     neg    ah
  226.     stosw
  227.     jmp    short send_pkt_4
  228. send_pkt_1:
  229.     mov    al,cl            ;store the length in cp.
  230.     neg    al
  231.     stosb
  232. send_pkt_4:
  233.     mov    ax,di            ;continue the put.
  234.     mov    al,cl            ;  advance the cp to its proper place.
  235.     neg    al
  236.     mov    di,ax
  237.     call    movemem
  238.  
  239. ;start the transmit.
  240.     mov    al,ENBL_XMT or (XMTPAGE shl 3)
  241.     loadport
  242.     setport    COMMAND
  243.     out    dx,al
  244.  
  245.     clc
  246.     ret
  247. send_pkt_toobig:
  248.     mov    dh,NO_SPACE
  249.     stc
  250.     ret
  251.  
  252.     public    get_address
  253. get_address:
  254. ;get the address of the interface.
  255. ;enter with es:di -> place to get the address, cx = size of address buffer.
  256. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  257.     assume    ds:code
  258.     cmp    cx,ARCADDR_LEN        ;make sure that we have enough room.
  259.     mov    dh,NO_SPACE
  260.     jb    get_address_2
  261.  
  262.     mov    al,my_arcnet_id        ;store our address.
  263.     stosb
  264.  
  265.     mov    cx,ARCADDR_LEN
  266.     clc
  267.     ret
  268. get_address_2:
  269.     stc
  270.     ret
  271.  
  272.  
  273. ;Set address on controller
  274.     public    set_address
  275. set_address:
  276.     assume    ds:nothing
  277. ;enter with ds:si -> address, CX = length of address.
  278. ;exit with nc if okay, or cy, dh=error if any errors.
  279.     mov    dh,CANT_SET
  280.     stc
  281.     ret
  282.  
  283.  
  284. rcv_mode_3:
  285. ;receive mode 3 is the only one we support, so we don't have to do anything.
  286.     ret
  287.  
  288.  
  289.     public    set_multicast_list
  290. set_multicast_list:
  291. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  292. ;return nc if we set all of them, or cy,dh=error if we didn't.
  293.     mov    dh,NO_MULTICAST
  294.     stc
  295.     ret
  296.  
  297.  
  298.     public    terminate
  299. terminate:
  300.     assume    ds:code
  301.     loadport
  302.     setport    IMASK
  303.     mov    al,0
  304.     out    dx,al
  305.  
  306.     setport COMMAND
  307.     mov    al,DSBL_RCV
  308.     out    dx,al
  309.     mov    al,DSBL_XMT
  310.     out    dx,al
  311.  
  312.     setport    STATUS            ;do we need to do this [rnn]?
  313.     in    al,dx
  314.  
  315.     ret
  316.  
  317.  
  318.     public    reset_interface
  319. reset_interface:
  320. ;reset the interface.
  321. ;we don't do anything.
  322.     ret
  323.  
  324.  
  325.     include    timeout.asm
  326.  
  327. ;called when we want to determine what to do with a received packet.
  328. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  329.     extrn    recv_find: near
  330.  
  331. ;called after we have copied the packet into the buffer.
  332. ;enter with ds:si ->the packet, cx = length of the packet.
  333.     extrn    recv_copy: near
  334.  
  335.     extrn    count_in_err: near
  336.     extrn    count_out_err: near
  337.  
  338.     public    recv
  339. recv:
  340. ;called from the recv isr.  All registers have been saved, and ds=cs.
  341. ;Upon exit, the interrupt will be acknowledged.
  342.     assume    ds:code
  343.  
  344. recv_1:
  345.     loadport            ;get the status to see if we got
  346.     setport    STATUS            ;  a false alarm.
  347.     in    al,dx
  348.     test    al,ST_RI
  349.     je    recv_2            ;yup, exit now.
  350.  
  351.     mov    es,mem_base
  352.     mov    bx,RCVPAGE * 512
  353.  
  354. ;decode data size.
  355.  
  356.     mov    cx,256            ;compute the actual length.
  357.     mov    al,es:[bx].arc_cp
  358.     or    al,al            ;is this a normal or continuation pkt?
  359.     jne    recv_3            ;go if normal.
  360.     mov    cx,512            ;extended packets have 512 max.
  361.     mov    al,es:[bx].arc_xcp
  362. recv_3:
  363.     xor    ah,ah
  364.     sub    cx,ax
  365.     add    cx,2            ;add in SID and DID.
  366.     mov    bl,al            ;use al as the low byte of the address.
  367.     mov    di,bx
  368.     mov    dl,driver_class
  369.     call    recv_find        ;look up our type.
  370.  
  371.     mov    ax,es            ;is this pointer null?
  372.     or    ax,di
  373.     je    recv_isr_9        ;yes - just free the frame.
  374.  
  375.     push    es            ;remember where the buffer pointer is.
  376.     push    di
  377.  
  378.     mov    ds,mem_base        ;copy the packet into their buffer.
  379.     assume    ds:nothing
  380.     mov    si,RCVPAGE * 512    ;  (don't worry about ds.
  381.     movsw                ;move SID and DID.
  382.     mov    ax,si
  383.     lodsb                ;get arc_cp.
  384.     or    al,al            ;extended?
  385.     jne    recv_5            ;no.
  386.     lodsb                ;yes - get arc_xcp.
  387. recv_5:
  388.     mov    si,ax            ;set the new pointer.
  389.     push    cx            ;move the data part of the packet.
  390.     sub    cx,2            ;don't move the two we've already
  391.     call    movemem            ;  moved.
  392.     pop    cx
  393.  
  394.     pop    si
  395.     pop    ds
  396.     assume    ds:nothing
  397.     call    recv_copy        ;tell them that we copied it.
  398.  
  399.     mov    ax,cs            ;restore our ds.
  400.     mov    ds,ax
  401.     assume    ds:code
  402.  
  403. recv_isr_9:
  404.  
  405.     loadport            ;enable reception again.
  406.     setport    COMMAND
  407.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST
  408.     out    dx,al
  409.  
  410.     jmp    recv_1
  411. recv_2:
  412.     ret
  413.  
  414.  
  415.     public    recv_exiting
  416. recv_exiting:
  417. ;called from the recv isr after interrupts have been acknowledged.
  418. ;Only ds and ax have been saved.
  419.     assume    ds:nothing
  420.     ret
  421.  
  422.  
  423. end_resident    label    byte
  424.  
  425.     public    usage_msg
  426. usage_msg    db    "usage: arcnet [-n] [-d] [-w] <packet_int_no> <int_no> <io_addr> <mem_base>",CR,LF,'$'
  427.  
  428.     public    copyright_msg
  429. copyright_msg    db    "Packet driver for the DataPoint RIM (ARCnet), version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  430.         db    "Portions Copyright 1988 Philip Prindeville",CR,LF,'$'
  431.  
  432. no_arcnet_msg    db    "No ARCnet found at that address.",CR,LF,'$'
  433. failed_test_msg    db    "Failed self test.",CR,LF,'$'
  434.  
  435. int_no_name    db    "Interrupt number ",'$'
  436. io_addr_name    db    "I/O port ",'$'
  437. mem_base_name    db    "Memory address ",'$'
  438.  
  439.     extrn    set_recv_isr: near
  440.  
  441. ;enter with si -> argument string, di -> word to store.
  442. ;if there is no number, don't change the number.
  443.     extrn    get_number: near
  444.  
  445. ;enter with dx -> name of word, di -> dword to print.
  446.     extrn    print_number: near
  447.  
  448.     public    parse_args
  449. parse_args:
  450. ;exit with nc if all went well, cy otherwise.
  451.     mov    di,offset int_no
  452.     call    get_number
  453.     mov    di,offset io_addr
  454.     call    get_number
  455.     mov    di,offset mem_base
  456.     call    get_number
  457.     clc
  458.     ret
  459.  
  460.  
  461. no_arcnet_error:
  462.     mov    dx,offset no_arcnet_msg
  463.     mov    ah,9
  464.     int    21h
  465.     jmp    short error
  466. failed_test_error:
  467.     mov    dx,offset failed_test_msg
  468.     mov    ah,9
  469.     int    21h
  470. error:
  471.     stc
  472.     ret
  473.  
  474.  
  475.     public    etopen
  476. etopen:
  477. ;reset the board via the I/O reset port, then wait for it to become sane again.
  478.  
  479.     mov    ax,mem_base        ;test the memory first.
  480.     mov    cx,2048
  481.     call    memory_test
  482.     jne    no_arcnet_error
  483.  
  484.     mov    es,mem_base
  485.  
  486.     loadport
  487.     setport SW_RST
  488.     in    al,dx
  489.  
  490.     mov    ax,RST_IVAL
  491.     call    set_timeout
  492. etopen_1:
  493.     call    do_timeout
  494.     jne    etopen_1
  495.  
  496.     setport    STATUS
  497.     in    al,dx
  498.  
  499. ;since we've just reset:
  500. ;    reset the POR flag,
  501. ;    check the diagnostic byte in the buffer,
  502. ;    grab the node ID, and assign it to the host number.
  503.  
  504.     test    al,ST_POR
  505.     je    etopen_2
  506.  
  507.     setport    COMMAND
  508.     mov    al,CLR_FLGS or FL_POR or FL_RECON
  509.     out    dx,al
  510.  
  511.     mov    al,es:[0]
  512.     cmp    byte ptr es:[0],TSTWRD
  513.     je    etopen_3
  514.     jmp    failed_test_error    ;failed power on self-test.
  515. etopen_3:
  516.     mov    al,es:[1]
  517.     mov    my_arcnet_id,al
  518. etopen_2:
  519.  
  520. ;another simple diagnostic:
  521. ;    force test flag on in RIM,
  522. ;    check to see that it is set,
  523. ;    reset it.
  524.  
  525.     loadport
  526.     setport    COMMAND
  527.     mov    al,LD_TST_FLG or FL_TST
  528.     out    dx,al
  529.  
  530.     setport STATUS
  531.     in    al,dx
  532.  
  533.     test    al,FL_TST
  534.     jne    etopen_4
  535.     jmp    failed_test_error    ;failed forced self-test.
  536. etopen_4:
  537.     setport    COMMAND
  538.     mov    al,LD_TST_FLG
  539.     out    dx,al
  540.     setport STATUS
  541.     in    al,dx
  542.  
  543.     pushf
  544.     cli
  545.  
  546.     call    set_recv_isr
  547.  
  548. ;now we enable the board to interrupt
  549. ;us on packet received.  Not transmiter available
  550. ;(i.e. transmission complete).  We don't have
  551. ;any control over POR, since it is NMI...
  552. ;RECON seems useless.
  553.  
  554.     loadport
  555.     setport    IMASK
  556.     mov    al,ST_RI
  557.     out    dx,al
  558.  
  559.     ; we should allow extended packets
  560.     setport    COMMAND
  561.     mov    al,DFN_CONF or CONF_XTND
  562.     out    dx,al
  563.  
  564.     mov    al,ENBL_RCV or (RCVPAGE shl 3) or BCAST;
  565.     out    dx,al
  566.  
  567.     popf
  568.  
  569.     mov    al, int_no        ; Get board's interrupt vector
  570.     add    al, 8
  571.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  572.     jb    set_int_num        ; No.
  573.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  574. set_int_num:
  575.     xor    ah, ah            ; Clear high byte
  576.     mov    int_num, ax        ; Set parameter_list int num.
  577.  
  578.     mov    dx,offset end_resident
  579.     clc
  580.     ret
  581.  
  582.     public    print_parameters
  583. print_parameters:
  584.     mov    di,offset int_no
  585.     mov    dx,offset int_no_name
  586.     call    print_number
  587.     mov    di,offset io_addr
  588.     mov    dx,offset io_addr_name
  589.     call    print_number
  590.     mov    di,offset mem_base
  591.     mov    dx,offset mem_base_name
  592.     call    print_number
  593.     ret
  594.  
  595.     include    memtest.asm
  596.  
  597. code    ends
  598.  
  599.     end
  600.